# _*_ coding:utf-8 _*_
# @Time  : 2023.04.12
# @Author: zizlee
""" Wind远程 """

import datetime
import pathlib
from fastapi import APIRouter, Header, Body, Query, BackgroundTasks, Form, UploadFile
from pydantic import BaseModel, constr, validator
from hutool import security
from db import FAConnection
from v1_all_api.all_utils import datetime_utils, file_utils
from v1_all_api.all_response import AllResponse
from configs import STATIC_FILE_HOST, FILE_STORAGE

from . import handler_utils

wind_remote_api = APIRouter()


MODULE_NAME = 'WindRemote'

# ---------------------------------------------------- 前端申请等 -------------------------------------------------------


# 创建项目
class CreatedItem(BaseModel):
    use_name: constr(max_length=200)
    position: constr(max_length=200)
    finish_time: str
    link_msg: constr(max_length=300)
    content: constr(max_length=500)

    @validator('finish_time')
    def validate_finish_time(cls, value):
        dt = datetime_utils.auth_datetime_string(value, f='%Y-%m-%d %H:%M:%S')
        if not dt:
            raise ValueError('日期格式错误,接受%Y-%m-%d %H:%M:%S型.')
        return dt


# 评价项目
class EvaluateItem(BaseModel):
    id: int
    evaluate: int
    evaluate_plain: str
    is_anonymous: bool


# 申请者提交一个申请
@wind_remote_api.post('/my/')
def create_record(ruizy_token: str = Header(...), record: CreatedItem = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 检查是否够申请积分
    need_quota, remain_quota = handler_utils.quota_information(module_name=MODULE_NAME, user_id=person['uid'])
    if need_quota > remain_quota:
        return AllResponse.validate_error(msg='申请所需积分为: {}，当前剩余：{}。'.format(need_quota, remain_quota))
    # 将数据保存
    sql = """
      INSERT INTO prse_wind_remote (creator,use_name,position,finish_time,link_msg,content,state,quota)
      VALUES (%s,%s,%s,%s,%s,%s,%s,%s);
    """
    prm = (person['uid'], record.use_name, record.position, record.finish_time, record.link_msg, record.content,
           0, need_quota)
    with FAConnection() as cursor:
        c = cursor.execute(sql, prm)
        if c:
            cursor.execute('SELECT LAST_INSERT_ID() AS insertID;')
            insert_id = cursor.fetchone()['insertID']
            # 申请成功，扣取积分
            handler_utils.quota_change_log(user_id=person['uid'], prse_id=insert_id, cursor=cursor,
                                           change=need_quota, module_key=MODULE_NAME)
    return AllResponse.create_successfully(msg='提交成功，请前往记录查看.') if c else AllResponse.server_error()


@wind_remote_api.get('/my/')
def query_my_record(ruizy_token: str = Header(...),
                    page: int = Query(...), page_size: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 查询自己的申请记录
    sql = """
      SELECT * FROM prse_wind_remote WHERE creator=%s ORDER BY create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [person['uid']], page=page, page_size=page_size)
    states = {
        -1: '拒绝',
        0: '等待中',
        1: '进行中',
        2: '完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['finish_time'] = datetime_utils.to_string(row['finish_time'], is_time=True)
        row['expire_time'] = datetime_utils.to_string(row['expire_time'], is_time=False)
        row['state_text'] = states.get(row['state'], '未知')
        row['annex_public'] = True if row['annex_public'] else False
        if row['annex'] and row['annex_public']:
            row['has_annex'] = True
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
        else:
            row['annex_url'] = ''
            row['annex_name'] = '无'
            row['has_annex'] = False
        del row['annex']
    return AllResponse.operate_successfully(data=ret)


# 对一个申请结果评价
@wind_remote_api.post('/myEvaluate/')
def evaluate_my_record(ruizy_token: str = Header(...), evaluate: EvaluateItem = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 检查是否评价过了
    sql = """
      UPDATE prse_wind_remote SET evaluate=%s,evaluate_plain=%s,is_anonymous=%s WHERE id=%s AND creator=%s LIMIT 1;
    """
    prm = (evaluate.evaluate, evaluate.evaluate_plain, evaluate.is_anonymous, evaluate.id, person['uid'])
    with FAConnection() as cursor:
        cursor.execute('SELECT id,evaluate,annex_name,annex,annex_public FROM prse_wind_remote WHERE id=%s AND creator=%s LIMIT 1;',
                       (evaluate.id, person['uid']))
        obj = cursor.fetchone()
        if not obj:
            return AllResponse.no_do_anything(msg='未检测到该条数据，评价失败.')
        if obj['evaluate'] and obj['evaluate'] > 0:
            return AllResponse.validate_error(msg='您已经评价过，无需重复评价.')
        cursor.execute(sql, prm)
    # add_work_lecture(evaluate.id)
    # 返回附件地址
    annex_url = ''
    if obj['annex'] and obj['annex_public']:
        annex_url = STATIC_FILE_HOST + obj['annex']
    return AllResponse.operate_successfully(msg='评价成功', data={
        'evaluate': evaluate.evaluate, 'id': evaluate.id, 'annex_url': annex_url,
        'has_annex': True if annex_url else False
    })


# 预览材料文件
@wind_remote_api.get('/my/dataPreView/')
def preview_record_file(ruizy_token: str = Header(...), rid: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 查询数据资料
    with FAConnection() as cursor:
        cursor.execute('SELECT id,use_name,annex FROM prse_wind_remote WHERE id=%s LIMIT 1;', (rid, ))
        obj = cursor.fetchone()
        if not obj:
            return AllResponse.server_no_content(msg='数据不存在')
    if not obj['annex']:
        return AllResponse.validate_error('还没有资料文件')
    # 资料文件
    annex_file = pathlib.Path(FILE_STORAGE).joinpath(obj['annex'])
    if not annex_file.exists():
        return AllResponse.server_no_content(msg='数据资料不存在')
    # 读取预览图片文件
    preview_folder = annex_file.parent.joinpath(annex_file.name + 'img')
    if preview_folder.exists() and not preview_folder.is_file():
        # 存在着预览的图片文件，读取文件信息
        if annex_file.name.endswith('.ppt') or annex_file.name.endswith('.pptx'):
            images = file_utils.get_file_list(preview_folder, glob='*.jpg', replaces=['幻灯片', '.JPG'])
        else:
            images = file_utils.get_file_list(preview_folder, glob='*.png')
    else:
        # 不存在，就得转化
        images = handler_utils.covert_file2image(annex_file)
        if len(images) < 1:
            return AllResponse.validate_error(msg='不支持预览的资料')
    images = [str(i).replace('\\', '/').replace(FILE_STORAGE, STATIC_FILE_HOST) for i in images]
    return AllResponse.operate_successfully(data={
        'id': rid,
        'topic': obj['use_name'],
        'images': images
    })

# ---------------------------------------------------- 管理员处理 -------------------------------------------------------


# 管理员查询
@wind_remote_api.get('/manage/')
def query_manage_record(ruizy_token: str = Header(...), page: int = Query(1), page_size: int = Query(30), state: int = Query(0)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if not security.operator_is_manager(person):
        return AllResponse.forbidden_error()
    sql = """
        SELECT a.*,u.admin_name FROM prse_wind_remote As a INNER JOIN ruizy_user As u ON a.creator=u.id
        WHERE a.state=%s ORDER BY a.create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [state], page=page, page_size=page_size)
    states = {
        -1: '拒绝',
        0: '等待',
        1: '通过',
        2: '完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['finish_time'] = datetime_utils.to_string(row['finish_time'], is_time=True)
        row['expire_time'] = datetime_utils.to_string(row['expire_time'], is_time=False)
        row['state_text'] = states.get(row['state'], '未知')
        if row['annex']:
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
            del row['annex']
    return AllResponse.operate_successfully(data=ret)


# 管理员完成
@wind_remote_api.post('/finish/')
async def finish_apply_record(bg_tasks: BackgroundTasks, ruizy_token: str = Header(...), state: int = Form(...), state_plain: str = Form(''),
                              rid: int = Form(...), annex_public: bool = Form(False), annex: UploadFile = Form(None)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if annex:
        # 写入文件
        save_path, sql_path = file_utils.get_file_paths(module_name='ProductService/PptCourseware', filename=annex.filename,
                                                        hashed=True)
        annex_content = await annex.read()
        with open(save_path, 'wb') as fp:
            fp.write(annex_content)
        annex_name = annex.filename
    else:
        save_path = ''
        sql_path = ''
        annex_name = ''
    # 计算一年后的日期
    expire_time = (datetime.datetime.now() + datetime.timedelta(days=365)).strftime('%Y-%m-%d %H:%M:%S')
    # 更新数据
    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    annex_public = 1 if annex_public else 0
    if state == 1:
        state = 2
    sql = """
        UPDATE prse_wind_remote SET state=%s,state_plain=%s,worker_id=%s,dispatch_time=%s,expire_time=%s, 
        annex_name=%s,annex_time=%s,annex=%s,annex_public=%s WHERE id=%s LIMIT 1;
    """

    prm = [state, state_plain, person['uid'], now_time, expire_time, annex_name, now_time, sql_path, annex_public, rid]
    with FAConnection() as cursor:
        cursor.execute('SELECT * FROM prse_wind_remote WHERE id=%s LIMIT 1;', [rid])
        _obj = cursor.fetchone()
        if not _obj:
            return AllResponse.validate_error(msg='处理的记录不存在!')
        cursor.execute(sql, prm)  # 更新数据
        if state == -1:  # 当拒绝时应加回积分
            handler_utils.quota_change_log(user_id=person['uid'], prse_id=rid, cursor=cursor,
                                           change=-_obj['quota'], module_key=MODULE_NAME)
    # 添加work_lecture记录
    # bg_tasks.add_task(add_work_lecture, rid)
    bg_tasks.add_task(handler_utils.covert_file2image, pathlib.Path(save_path))  # 后台任务转为图片
    return AllResponse.operate_successfully(msg='完成wind远程申请!')


# class DispatchModel(BaseModel):
#     rid: int
#     worker_id: int
#     state: int
#     explain_state: str
#
#
# # 管理员分配任务
# @ppt_courseware_api.post('/manage/')
# def dispatch_apply_record(ruizy_token: str = Header(...), dispatch_item: DispatchModel = Body(...)):
#     person = security.decrypt_access_token(ruizy_token)
#     if not person:
#         return AllResponse.no_authorization()
#     if not security.operator_is_manager(person):
#         return AllResponse.forbidden_error()
#     now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
#     sql = "UPDATE prse_ppt SET state=%s,state_plain=%s,worker_id=%s,dispatch_time=%s WHERE id=%s LIMIT 1;"
#     prm = [dispatch_item.state, dispatch_item.explain_state, dispatch_item.worker_id, now_time, dispatch_item.rid]
#     with FAConnection() as cursor:
#         cursor.execute('SELECT * FROM prse_ppt WHERE id=%s LIMIT 1;', [dispatch_item.rid])
#         _obj = cursor.fetchone()
#         if not _obj:
#             return AllResponse.validate_error(msg='处理的记录不存在!')
#         cursor.execute(sql, prm)  # 执行更新
#         if dispatch_item.state == -1:  # 当拒绝时应加回积分
#             handler_utils.quota_change_log(user_id=person['uid'], prse_id=dispatch_item.rid, cursor=cursor,
#                                            change=-_obj['quota'], module_key=MODULE_NAME)
#     return AllResponse.operate_successfully(msg='处理申请记录成功!')
#
#
# ---------------------------------------------------- 任务员处理 -------------------------------------------------------


# 人员查询自己的任务
@wind_remote_api.get('/worker/')
def query_apply_record_tome(ruizy_token: str = Header(...), page: int = Query(1), page_size: int = Query(30), state: int = Query(0)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    sql = """
        SELECT a.*,u.admin_name FROM prse_wind_remote As a INNER JOIN ruizy_user As u ON a.creator=u.id
        WHERE a.state=%s AND a.worker_id=%s ORDER BY a.create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [state, person['uid']], page=page, page_size=page_size)
    states = {
        1: '待处理',
        2: '已完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['finish_time'] = datetime_utils.to_string(row['finish_time'], is_time=True)
        row['expire_time'] = datetime_utils.to_string(row['expire_time'], is_time=False)
        row['state_text'] = states.get(row['state'], '未知')
        if row['annex']:
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
            del row['annex']
    return AllResponse.operate_successfully(data=ret)

#
# # 人员上传附件材料
# @ppt_courseware_api.post('/worker/')
# async def finish_hedging_plan_tome(bg_tasks: BackgroundTasks, ruizy_token: str = Header(...),
#                                    rid: int = Form(...), annex_public: bool = Form(False), annex: UploadFile = Form(None)):
#     person = security.decrypt_access_token(ruizy_token)
#     if not person:
#         return AllResponse.no_authorization()
#     if annex:
#         # 写入文件
#         save_path, sql_path = file_utils.get_file_paths(module_name='ProductService/PptCourseware', filename=annex.filename,
#                                                         hashed=True)
#         annex_content = await annex.read()
#         with open(save_path, 'wb') as fp:
#             fp.write(annex_content)
#         annex_name = annex.filename
#     else:
#         save_path = ''
#         sql_path = ''
#         annex_name = ''
#     # 更新数据
#     now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
#     annex_public = 1 if annex_public else 0
#     sql = "UPDATE prse_ppt SET annex_name=%s,annex_time=%s,annex=%s,annex_public=%s,state=2 WHERE id=%s LIMIT 1;"
#     prm = [annex_name, now_time, sql_path, annex_public, rid]
#     with FAConnection() as cursor:
#         cursor.execute(sql, prm)
#     # 添加work_lecture记录
#     # bg_tasks.add_task(add_work_lecture, rid)
#     bg_tasks.add_task(handler_utils.covert_file2image, pathlib.Path(save_path))  # 后台任务转为图片
#     return AllResponse.operate_successfully(msg='完成PPT课件上传!')
#
